The renaming of the prefix makes this a large patch.
<title>API Reference</title>
<xi:include href="xml/GskRenderer.xml" />
<xi:include href="xml/GskRenderNode.xml" />
+ <xi:include href="xml/GskTransform.xml" />
</reference>
<index id="api-index-full">
gsk_rounded_rect_contains_rect
gsk_rounded_rect_intersects_rect
</SECTION>
+
+<SECTION>
+<FILE>GskTransform</FILE>
+<TITLE>3D transformations</TITLE>
+GskTransformType
+GskTransform
+gsk_transform_ref
+gsk_transform_unref
+<SUBSECTION>
+gsk_transform_print
+gsk_transform_to_string
+gsk_transform_to_matrix
+<SUBSECTION>
+gsk_transform_identity
+gsk_transform_transform
+gsk_transform_matrix
+gsk_transform_translate
+gsk_transform_translate_3d
+gsk_transform_rotate
+gsk_transform_rotate_3d
+gsk_transform_scale
+gsk_transform_scale_3d
+<SUBSECTION>
+gsk_transform_equal
+<SUBSECTION>
+gsk_transform_get_transform_type
+gsk_transform_get_next
+<SUBSECTION Private>
+GSK_TYPE_TRANSFORM
+gsk_transform_get_type
+gsk_transform_new
+</SECTION>
+
<xi:include href="xml/gtkselection.xml" />
<xi:include href="xml/gtktesting.xml" />
<xi:include href="xml/filesystem.xml" />
- <xi:include href="xml/gtktransform.xml" />
</part>
<part id="theming">
GtkMountOperationPrivate
</SECTION>
-<SECTION>
-<FILE>gtktransform</FILE>
-<TITLE>3D transformations</TITLE>
-GtkTransformType
-GtkTransform
-gtk_transform_ref
-gtk_transform_unref
-<SUBSECTION>
-gtk_transform_print
-gtk_transform_to_string
-gtk_transform_to_matrix
-<SUBSECTION>
-gtk_transform_identity
-gtk_transform_transform
-gtk_transform_matrix
-gtk_transform_translate
-gtk_transform_translate_3d
-gtk_transform_rotate
-gtk_transform_rotate_3d
-gtk_transform_scale
-gtk_transform_scale_3d
-<SUBSECTION>
-gtk_transform_equal
-<SUBSECTION>
-gtk_transform_get_transform_type
-gtk_transform_get_next
-<SUBSECTION Private>
-GTK_TYPE_TRANSFORM
-gdk_transform_get_type
-gtk_transform_new
-</SECTION>
-
<SECTION>
<FILE>gtkorientable</FILE>
<TITLE>Orientable</TITLE>
#include <gsk/gskrenderer.h>
#include <gsk/gskrendernode.h>
#include <gsk/gskroundedrect.h>
+#include <gsk/gsktransform.h>
#include <gsk/gsktypes.h>
#include <gsk/gskenumtypes.h>
--- /dev/null
+/*
+ * Copyright © 2019 Benjamin Otte
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Benjamin Otte <otte@gnome.org>
+ */
+
+
+/**
+ * SECTION:gsktransform
+ * @Title: GskTransform
+ * @Short_description: A description for transform operations
+ *
+ * #GskTransform is an object to describe transform matrices. Unlike
+ * #graphene_matrix_t, #GskTransform retains the steps in how a transform was
+ * constructed, and allows inspecting them. It is modeled after the way
+ * CSS describes transforms.
+ *
+ * #GskTransform objects are immutable and cannot be changed after creation.
+ * This means code can safely expose them as properties of objects without
+ * having to worry about others changing them.
+ */
+
+#include "config.h"
+
+#include "gsktransformprivate.h"
+
+typedef struct _GskTransformClass GskTransformClass;
+
+#define GSK_IS_TRANSFORM_TYPE(self,type) ((self) == NULL ? (type) == GSK_TRANSFORM_TYPE_IDENTITY : (self)->transform_class->transform_type == (type))
+
+struct _GskTransform
+{
+ const GskTransformClass *transform_class;
+
+ volatile int ref_count;
+ GskTransform *next;
+};
+
+struct _GskTransformClass
+{
+ GskTransformType transform_type;
+ gsize struct_size;
+ const char *type_name;
+
+ void (* finalize) (GskTransform *transform);
+ GskMatrixCategory (* categorize) (GskTransform *transform);
+ void (* to_matrix) (GskTransform *transform,
+ graphene_matrix_t *out_matrix);
+ gboolean (* apply_affine) (GskTransform *transform,
+ float *out_scale_x,
+ float *out_scale_y,
+ float *out_dx,
+ float *out_dy);
+ void (* print) (GskTransform *transform,
+ GString *string);
+ GskTransform * (* apply) (GskTransform *transform,
+ GskTransform *apply_to);
+ /* both matrices have the same type */
+ gboolean (* equal) (GskTransform *first_transform,
+ GskTransform *second_transform);
+};
+
+/**
+ * GskTransform: (ref-func gsk_transform_ref) (unref-func gsk_transform_unref)
+ *
+ * The `GskTransform` structure contains only private data.
+ */
+
+G_DEFINE_BOXED_TYPE (GskTransform, gsk_transform,
+ gsk_transform_ref,
+ gsk_transform_unref)
+
+/*<private>
+ * gsk_transform_is_identity:
+ * @transform: (allow-none): A transform or %NULL
+ *
+ * Checks if the transform is a representation of the identity
+ * transform.
+ *
+ * This is different from a transform like `scale(2) scale(0.5)`
+ * which just results in an identity transform when simplified.
+ *
+ * Returns: %TRUE if this transform is a representation of
+ * the identity transform
+ **/
+static gboolean
+gsk_transform_is_identity (GskTransform *self)
+{
+ return self == NULL ||
+ (GSK_IS_TRANSFORM_TYPE (self, GSK_TRANSFORM_TYPE_IDENTITY) && gsk_transform_is_identity (self->next));
+}
+
+/*< private >
+ * gsk_transform_alloc:
+ * @transform_class: class structure for this self
+ * @next: (transfer full) Next matrix to multiply with or %NULL if none
+ *
+ * Returns: (transfer full): the newly created #GskTransform
+ */
+static gpointer
+gsk_transform_alloc (const GskTransformClass *transform_class,
+ GskTransform *next)
+{
+ GskTransform *self;
+
+ g_return_val_if_fail (transform_class != NULL, NULL);
+
+ self = g_malloc0 (transform_class->struct_size);
+
+ self->transform_class = transform_class;
+ self->ref_count = 1;
+ self->next = gsk_transform_is_identity (next) ? NULL : next;
+
+ return self;
+}
+
+/*** IDENTITY ***/
+
+static void
+gsk_identity_transform_finalize (GskTransform *transform)
+{
+}
+
+static GskMatrixCategory
+gsk_identity_transform_categorize (GskTransform *transform)
+{
+ return GSK_MATRIX_CATEGORY_IDENTITY;
+}
+
+static void
+gsk_identity_transform_to_matrix (GskTransform *transform,
+ graphene_matrix_t *out_matrix)
+{
+ graphene_matrix_init_identity (out_matrix);
+}
+
+static gboolean
+gsk_identity_transform_apply_affine (GskTransform *transform,
+ float *out_scale_x,
+ float *out_scale_y,
+ float *out_dx,
+ float *out_dy)
+{
+ return TRUE;
+}
+
+static void
+gsk_identity_transform_print (GskTransform *transform,
+ GString *string)
+{
+ g_string_append (string, "identity");
+}
+
+static GskTransform *
+gsk_identity_transform_apply (GskTransform *transform,
+ GskTransform *apply_to)
+{
+ return gsk_transform_identity (apply_to);
+}
+
+static gboolean
+gsk_identity_transform_equal (GskTransform *first_transform,
+ GskTransform *second_transform)
+{
+ return TRUE;
+}
+
+static const GskTransformClass GSK_IDENTITY_TRANSFORM_CLASS =
+{
+ GSK_TRANSFORM_TYPE_IDENTITY,
+ sizeof (GskTransform),
+ "GskIdentityMatrix",
+ gsk_identity_transform_finalize,
+ gsk_identity_transform_categorize,
+ gsk_identity_transform_to_matrix,
+ gsk_identity_transform_apply_affine,
+ gsk_identity_transform_print,
+ gsk_identity_transform_apply,
+ gsk_identity_transform_equal,
+};
+
+/**
+ * gsk_transform_identity:
+ * @next: (allow-none): the next transform operation or %NULL
+ *
+ * Adds an identity multiplication into the list of matrix operations.
+ *
+ * This operation is generally useless, but may be useful when interpolating
+ * matrices, because the identity matrix can be interpolated to and from
+ * everything, so an identity matrix can be used as a keyframe between two
+ * different types of matrices.
+ *
+ * Returns: The new matrix
+ **/
+GskTransform *
+gsk_transform_identity (GskTransform *next)
+{
+ if (gsk_transform_is_identity (next))
+ return next;
+
+ return gsk_transform_alloc (&GSK_IDENTITY_TRANSFORM_CLASS, next);
+}
+
+/*** MATRIX ***/
+
+typedef struct _GskMatrixTransform GskMatrixTransform;
+
+struct _GskMatrixTransform
+{
+ GskTransform parent;
+
+ graphene_matrix_t matrix;
+ GskMatrixCategory category;
+};
+
+static void
+gsk_matrix_transform_finalize (GskTransform *self)
+{
+}
+
+static GskMatrixCategory
+gsk_matrix_transform_categorize (GskTransform *transform)
+{
+ GskMatrixTransform *self = (GskMatrixTransform *) transform;
+
+ return self->category;
+}
+
+static void
+gsk_matrix_transform_to_matrix (GskTransform *transform,
+ graphene_matrix_t *out_matrix)
+{
+ GskMatrixTransform *self = (GskMatrixTransform *) transform;
+
+ graphene_matrix_init_from_matrix (out_matrix, &self->matrix);
+}
+
+static gboolean
+gsk_matrix_transform_apply_affine (GskTransform *transform,
+ float *out_scale_x,
+ float *out_scale_y,
+ float *out_dx,
+ float *out_dy)
+{
+ GskMatrixTransform *self = (GskMatrixTransform *) transform;
+
+ switch (self->category)
+ {
+ case GSK_MATRIX_CATEGORY_UNKNOWN:
+ case GSK_MATRIX_CATEGORY_ANY:
+ case GSK_MATRIX_CATEGORY_INVERTIBLE:
+ default:
+ return FALSE;
+
+ case GSK_MATRIX_CATEGORY_2D_AFFINE:
+ *out_dx += *out_scale_x * graphene_matrix_get_value (&self->matrix, 3, 0);
+ *out_dy += *out_scale_y * graphene_matrix_get_value (&self->matrix, 3, 1);
+ *out_scale_x *= graphene_matrix_get_value (&self->matrix, 0, 0);
+ *out_scale_y *= graphene_matrix_get_value (&self->matrix, 1, 1);
+ return TRUE;
+
+ case GSK_MATRIX_CATEGORY_2D_TRANSLATE:
+ *out_dx += *out_scale_x * graphene_matrix_get_value (&self->matrix, 3, 0);
+ *out_dy += *out_scale_y * graphene_matrix_get_value (&self->matrix, 3, 1);
+ return TRUE;
+
+ case GSK_MATRIX_CATEGORY_IDENTITY:
+ return TRUE;
+ }
+}
+
+static void
+string_append_double (GString *string,
+ double d)
+{
+ char buf[G_ASCII_DTOSTR_BUF_SIZE];
+
+ g_ascii_formatd (buf, G_ASCII_DTOSTR_BUF_SIZE, "%g", d);
+ g_string_append (string, buf);
+}
+
+static void
+gsk_matrix_transform_print (GskTransform *transform,
+ GString *string)
+{
+ GskMatrixTransform *self = (GskMatrixTransform *) transform;
+ guint i;
+ float f[16];
+
+ g_string_append (string, "matrix3d(");
+ graphene_matrix_to_float (&self->matrix, f);
+ for (i = 0; i < 16; i++)
+ {
+ if (i > 0)
+ g_string_append (string, ", ");
+ string_append_double (string, f[i]);
+ }
+ g_string_append (string, ")");
+}
+
+static GskTransform *
+gsk_matrix_transform_apply (GskTransform *transform,
+ GskTransform *apply_to)
+{
+ GskMatrixTransform *self = (GskMatrixTransform *) transform;
+
+ return gsk_transform_matrix_with_category (apply_to,
+ &self->matrix,
+ self->category);
+}
+
+static gboolean
+gsk_matrix_transform_equal (GskTransform *first_transform,
+ GskTransform *second_transform)
+{
+ GskMatrixTransform *first = (GskMatrixTransform *) first_transform;
+ GskMatrixTransform *second = (GskMatrixTransform *) second_transform;
+
+ /* Crude, but better than just returning FALSE */
+ return memcmp (&first->matrix, &second->matrix, sizeof (graphene_matrix_t)) == 0;
+}
+
+static const GskTransformClass GSK_TRANSFORM_TRANSFORM_CLASS =
+{
+ GSK_TRANSFORM_TYPE_TRANSFORM,
+ sizeof (GskMatrixTransform),
+ "GskMatrixTransform",
+ gsk_matrix_transform_finalize,
+ gsk_matrix_transform_categorize,
+ gsk_matrix_transform_to_matrix,
+ gsk_matrix_transform_apply_affine,
+ gsk_matrix_transform_print,
+ gsk_matrix_transform_apply,
+ gsk_matrix_transform_equal,
+};
+
+GskTransform *
+gsk_transform_matrix_with_category (GskTransform *next,
+ const graphene_matrix_t *matrix,
+ GskMatrixCategory category)
+{
+ GskMatrixTransform *result = gsk_transform_alloc (&GSK_TRANSFORM_TRANSFORM_CLASS, next);
+
+ graphene_matrix_init_from_matrix (&result->matrix, matrix);
+ result->category = category;
+
+ return &result->parent;
+}
+
+/**
+ * gsk_transform_matrix:
+ * @next: (allow-none): the next transform
+ * @matrix: the matrix to multiply @next with
+ *
+ * Multiplies @next with the given @matrix.
+ *
+ * Returns: The new matrix
+ **/
+GskTransform *
+gsk_transform_matrix (GskTransform *next,
+ const graphene_matrix_t *matrix)
+{
+ return gsk_transform_matrix_with_category (next, matrix, GSK_MATRIX_CATEGORY_UNKNOWN);
+}
+
+/*** TRANSLATE ***/
+
+typedef struct _GskTranslateTransform GskTranslateTransform;
+
+struct _GskTranslateTransform
+{
+ GskTransform parent;
+
+ graphene_point3d_t point;
+};
+
+static void
+gsk_translate_transform_finalize (GskTransform *self)
+{
+}
+
+static GskMatrixCategory
+gsk_translate_transform_categorize (GskTransform *transform)
+{
+ GskTranslateTransform *self = (GskTranslateTransform *) transform;
+
+ if (self->point.z != 0.0)
+ return GSK_MATRIX_CATEGORY_INVERTIBLE;
+
+ return GSK_MATRIX_CATEGORY_2D_TRANSLATE;
+}
+
+static void
+gsk_translate_transform_to_matrix (GskTransform *transform,
+ graphene_matrix_t *out_matrix)
+{
+ GskTranslateTransform *self = (GskTranslateTransform *) transform;
+
+ graphene_matrix_init_translate (out_matrix, &self->point);
+}
+
+static gboolean
+gsk_translate_transform_apply_affine (GskTransform *transform,
+ float *out_scale_x,
+ float *out_scale_y,
+ float *out_dx,
+ float *out_dy)
+{
+ GskTranslateTransform *self = (GskTranslateTransform *) transform;
+
+ if (self->point.z != 0.0)
+ return FALSE;
+
+ *out_dx += *out_scale_x * self->point.x;
+ *out_dy += *out_scale_y * self->point.y;
+
+ return TRUE;
+}
+
+static GskTransform *
+gsk_translate_transform_apply (GskTransform *transform,
+ GskTransform *apply_to)
+{
+ GskTranslateTransform *self = (GskTranslateTransform *) transform;
+
+ return gsk_transform_translate_3d (apply_to, &self->point);
+}
+
+static gboolean
+gsk_translate_transform_equal (GskTransform *first_transform,
+ GskTransform *second_transform)
+{
+ GskTranslateTransform *first = (GskTranslateTransform *) first_transform;
+ GskTranslateTransform *second = (GskTranslateTransform *) second_transform;
+
+ return graphene_point3d_equal (&first->point, &second->point);
+}
+
+static void
+gsk_translate_transform_print (GskTransform *transform,
+ GString *string)
+{
+ GskTranslateTransform *self = (GskTranslateTransform *) transform;
+
+ if (self->point.z == 0)
+ g_string_append (string, "translate(");
+ else
+ g_string_append (string, "translate3d(");
+
+ string_append_double (string, self->point.x);
+ g_string_append (string, ", ");
+ string_append_double (string, self->point.y);
+ if (self->point.z != 0)
+ {
+ g_string_append (string, ", ");
+ string_append_double (string, self->point.y);
+ }
+ g_string_append (string, ")");
+}
+
+static const GskTransformClass GSK_TRANSLATE_TRANSFORM_CLASS =
+{
+ GSK_TRANSFORM_TYPE_TRANSLATE,
+ sizeof (GskTranslateTransform),
+ "GskTranslateTransform",
+ gsk_translate_transform_finalize,
+ gsk_translate_transform_categorize,
+ gsk_translate_transform_to_matrix,
+ gsk_translate_transform_apply_affine,
+ gsk_translate_transform_print,
+ gsk_translate_transform_apply,
+ gsk_translate_transform_equal,
+};
+
+/**
+ * gsk_transform_translate:
+ * @next: (allow-none): the next transform
+ * @point: the point to translate the matrix by
+ *
+ * Translates @next in 2dimensional space by @point.
+ *
+ * Returns: The new matrix
+ **/
+GskTransform *
+gsk_transform_translate (GskTransform *next,
+ const graphene_point_t *point)
+{
+ graphene_point3d_t point3d;
+
+ graphene_point3d_init (&point3d, point->x, point->y, 0);
+
+ return gsk_transform_translate_3d (next, &point3d);
+}
+
+/**
+ * gsk_transform_translate_3d:
+ * @next: (allow-none): the next transform
+ * @point: the point to translate the matrix by
+ *
+ * Translates @next by @point.
+ *
+ * Returns: The new matrix
+ **/
+GskTransform *
+gsk_transform_translate_3d (GskTransform *next,
+ const graphene_point3d_t *point)
+{
+ GskTranslateTransform *result = gsk_transform_alloc (&GSK_TRANSLATE_TRANSFORM_CLASS, next);
+
+ graphene_point3d_init_from_point (&result->point, point);
+
+ return &result->parent;
+}
+
+/*** ROTATE ***/
+
+typedef struct _GskRotateTransform GskRotateTransform;
+
+struct _GskRotateTransform
+{
+ GskTransform parent;
+
+ float angle;
+ graphene_vec3_t axis;
+};
+
+static void
+gsk_rotate_transform_finalize (GskTransform *self)
+{
+}
+
+static GskMatrixCategory
+gsk_rotate_transform_categorize (GskTransform *transform)
+{
+ return GSK_MATRIX_CATEGORY_INVERTIBLE;
+}
+
+static void
+gsk_rotate_transform_to_matrix (GskTransform *transform,
+ graphene_matrix_t *out_matrix)
+{
+ GskRotateTransform *self = (GskRotateTransform *) transform;
+
+ graphene_matrix_init_rotate (out_matrix, self->angle, &self->axis);
+}
+
+static gboolean
+gsk_rotate_transform_apply_affine (GskTransform *transform,
+ float *out_scale_x,
+ float *out_scale_y,
+ float *out_dx,
+ float *out_dy)
+{
+ return FALSE;
+}
+
+static GskTransform *
+gsk_rotate_transform_apply (GskTransform *transform,
+ GskTransform *apply_to)
+{
+ GskRotateTransform *self = (GskRotateTransform *) transform;
+
+ return gsk_transform_rotate_3d (apply_to, self->angle, &self->axis);
+}
+
+static gboolean
+gsk_rotate_transform_equal (GskTransform *first_transform,
+ GskTransform *second_transform)
+{
+ GskRotateTransform *first = (GskRotateTransform *) first_transform;
+ GskRotateTransform *second = (GskRotateTransform *) second_transform;
+
+ return first->angle == second->angle
+ && graphene_vec3_equal (&first->axis, &second->axis);
+}
+
+static void
+gsk_rotate_transform_print (GskTransform *transform,
+ GString *string)
+{
+ GskRotateTransform *self = (GskRotateTransform *) transform;
+ graphene_vec3_t default_axis;
+
+ graphene_vec3_init_from_vec3 (&default_axis, graphene_vec3_z_axis ());
+ if (graphene_vec3_equal (&default_axis, &self->axis))
+ {
+ g_string_append (string, "rotate(");
+ string_append_double (string, self->angle);
+ g_string_append (string, ")");
+ }
+ else
+ {
+ float f[3];
+ guint i;
+
+ g_string_append (string, "rotate3d(");
+ graphene_vec3_to_float (&self->axis, f);
+ for (i = 0; i < 3; i++)
+ {
+ string_append_double (string, f[i]);
+ g_string_append (string, ", ");
+ }
+ string_append_double (string, self->angle);
+ g_string_append (string, ")");
+ }
+}
+
+static const GskTransformClass GSK_ROTATE_TRANSFORM_CLASS =
+{
+ GSK_TRANSFORM_TYPE_ROTATE,
+ sizeof (GskRotateTransform),
+ "GskRotateTransform",
+ gsk_rotate_transform_finalize,
+ gsk_rotate_transform_categorize,
+ gsk_rotate_transform_to_matrix,
+ gsk_rotate_transform_apply_affine,
+ gsk_rotate_transform_print,
+ gsk_rotate_transform_apply,
+ gsk_rotate_transform_equal,
+};
+
+/**
+ * gsk_transform_rotate:
+ * @next: (allow-none): the next transform
+ * @angle: the rotation angle, in degrees (clockwise)
+ *
+ * Rotates @next @angle degrees in 2D - or in 3Dspeak, around the z axis.
+ *
+ * Returns: The new matrix
+ **/
+GskTransform *
+gsk_transform_rotate (GskTransform *next,
+ float angle)
+{
+ return gsk_transform_rotate_3d (next, angle, graphene_vec3_z_axis ());
+}
+
+/**
+ * gsk_transform_rotate_3d:
+ * @next: (allow-none): the next transform
+ * @angle: the rotation angle, in degrees (clockwise)
+ * @axis: The rotation axis
+ *
+ * Rotates @next @angle degrees around @axis.
+ *
+ * For a rotation in 2D space, use gsk_transform_rotate().
+ *
+ * Returns: The new matrix
+ **/
+GskTransform *
+gsk_transform_rotate_3d (GskTransform *next,
+ float angle,
+ const graphene_vec3_t *axis)
+{
+ GskRotateTransform *result = gsk_transform_alloc (&GSK_ROTATE_TRANSFORM_CLASS, next);
+
+ result->angle = angle;
+ graphene_vec3_init_from_vec3 (&result->axis, axis);
+
+ return &result->parent;
+}
+
+/*** SCALE ***/
+
+typedef struct _GskScaleTransform GskScaleTransform;
+
+struct _GskScaleTransform
+{
+ GskTransform parent;
+
+ float factor_x;
+ float factor_y;
+ float factor_z;
+};
+
+static void
+gsk_scale_transform_finalize (GskTransform *self)
+{
+}
+
+static GskMatrixCategory
+gsk_scale_transform_categorize (GskTransform *transform)
+{
+ GskScaleTransform *self = (GskScaleTransform *) transform;
+
+ if (self->factor_z != 1.0)
+ return GSK_MATRIX_CATEGORY_INVERTIBLE;
+
+ return GSK_MATRIX_CATEGORY_2D_AFFINE;
+}
+
+static void
+gsk_scale_transform_to_matrix (GskTransform *transform,
+ graphene_matrix_t *out_matrix)
+{
+ GskScaleTransform *self = (GskScaleTransform *) transform;
+
+ graphene_matrix_init_scale (out_matrix, self->factor_x, self->factor_y, self->factor_z);
+}
+
+static gboolean
+gsk_scale_transform_apply_affine (GskTransform *transform,
+ float *out_scale_x,
+ float *out_scale_y,
+ float *out_dx,
+ float *out_dy)
+{
+ GskScaleTransform *self = (GskScaleTransform *) transform;
+
+ if (self->factor_z != 1.0)
+ return FALSE;
+
+ *out_scale_x *= self->factor_x;
+ *out_scale_y *= self->factor_y;
+
+ return TRUE;
+}
+
+static GskTransform *
+gsk_scale_transform_apply (GskTransform *transform,
+ GskTransform *apply_to)
+{
+ GskScaleTransform *self = (GskScaleTransform *) transform;
+
+ return gsk_transform_scale_3d (apply_to, self->factor_x, self->factor_y, self->factor_z);
+}
+
+static gboolean
+gsk_scale_transform_equal (GskTransform *first_transform,
+ GskTransform *second_transform)
+{
+ GskScaleTransform *first = (GskScaleTransform *) first_transform;
+ GskScaleTransform *second = (GskScaleTransform *) second_transform;
+
+ return first->factor_x == second->factor_x
+ && first->factor_y == second->factor_y
+ && first->factor_z == second->factor_z;
+}
+
+static void
+gsk_scale_transform_print (GskTransform *transform,
+ GString *string)
+{
+ GskScaleTransform *self = (GskScaleTransform *) transform;
+
+ if (self->factor_z == 1.0)
+ {
+ g_string_append (string, "scale(");
+ string_append_double (string, self->factor_x);
+ if (self->factor_x != self->factor_y)
+ {
+ g_string_append (string, ", ");
+ string_append_double (string, self->factor_y);
+ }
+ g_string_append (string, ")");
+ }
+ else
+ {
+ g_string_append (string, "scale3d(");
+ string_append_double (string, self->factor_x);
+ g_string_append (string, ", ");
+ string_append_double (string, self->factor_y);
+ g_string_append (string, ", ");
+ string_append_double (string, self->factor_z);
+ g_string_append (string, ")");
+ }
+}
+
+static const GskTransformClass GSK_SCALE_TRANSFORM_CLASS =
+{
+ GSK_TRANSFORM_TYPE_SCALE,
+ sizeof (GskScaleTransform),
+ "GskScaleTransform",
+ gsk_scale_transform_finalize,
+ gsk_scale_transform_categorize,
+ gsk_scale_transform_to_matrix,
+ gsk_scale_transform_apply_affine,
+ gsk_scale_transform_print,
+ gsk_scale_transform_apply,
+ gsk_scale_transform_equal,
+};
+
+/**
+ * gsk_transform_scale:
+ * @next: (allow-none): the next transform
+ * @factor_x: scaling factor on the X axis
+ * @factor_y: scaling factor on the Y axis
+ *
+ * Scales @next in 2-dimensional space by the given factors.
+ * Use gsk_transform_scale_3d() to scale in all 3 dimensions.
+ *
+ * Returns: The new matrix
+ **/
+GskTransform *
+gsk_transform_scale (GskTransform *next,
+ float factor_x,
+ float factor_y)
+{
+ return gsk_transform_scale_3d (next, factor_x, factor_y, 1.0);
+}
+
+/**
+ * gsk_transform_scale_3d:
+ * @next: (allow-none): the next transform
+ * @factor_x: scaling factor on the X axis
+ * @factor_y: scaling factor on the Y axis
+ * @factor_z: scaling factor on the Z axis
+ *
+ * Scales @next by the given factors.
+ *
+ * Returns: The new matrix
+ **/
+GskTransform *
+gsk_transform_scale_3d (GskTransform *next,
+ float factor_x,
+ float factor_y,
+ float factor_z)
+{
+ GskScaleTransform *result = gsk_transform_alloc (&GSK_SCALE_TRANSFORM_CLASS, next);
+
+ result->factor_x = factor_x;
+ result->factor_y = factor_y;
+ result->factor_z = factor_z;
+
+ return &result->parent;
+}
+
+/*** PUBLIC API ***/
+
+static void
+gsk_transform_finalize (GskTransform *self)
+{
+ self->transform_class->finalize (self);
+
+ gsk_transform_unref (self->next);
+
+ g_free (self);
+}
+
+/**
+ * gsk_transform_ref:
+ * @self: (allow-none): a #GskTransform
+ *
+ * Acquires a reference on the given #GskTransform.
+ *
+ * Returns: (transfer none): the #GskTransform with an additional reference
+ */
+GskTransform *
+gsk_transform_ref (GskTransform *self)
+{
+ if (self == NULL)
+ return NULL;
+
+ g_atomic_int_inc (&self->ref_count);
+
+ return self;
+}
+
+/**
+ * gsk_transform_unref:
+ * @self: (allow-none): a #GskTransform
+ *
+ * Releases a reference on the given #GskTransform.
+ *
+ * If the reference was the last, the resources associated to the @self are
+ * freed.
+ */
+void
+gsk_transform_unref (GskTransform *self)
+{
+ if (self == NULL)
+ return;
+
+ if (g_atomic_int_dec_and_test (&self->ref_count))
+ gsk_transform_finalize (self);
+}
+
+/**
+ * gsk_transform_print:
+ * @self: (allow-none): a #GskTransform
+ * @string: The string to print into
+ *
+ * Converts @self into a string representation suitable for printing that
+ * can later be parsed with gsk_transform_parse().
+ **/
+void
+gsk_transform_print (GskTransform *self,
+ GString *string)
+{
+ g_return_if_fail (string != NULL);
+
+ if (self == NULL)
+ {
+ g_string_append (string, "none");
+ return;
+ }
+
+ if (self->next != NULL)
+ {
+ gsk_transform_print (self->next, string);
+ g_string_append (string, " ");
+ }
+
+ self->transform_class->print (self, string);
+}
+
+/**
+ * gsk_transform_to_string:
+ * @self: (allow-none): a #GskTransform
+ *
+ * Converts a matrix into a string that is suitable for
+ * printing and can later be parsed with gsk_transform_parse().
+ *
+ * This is a wrapper around gsk_transform_print(), see that function
+ * for details.
+ *
+ * Returns: A new string for @self
+ **/
+char *
+gsk_transform_to_string (GskTransform *self)
+{
+ GString *string;
+
+ string = g_string_new ("");
+
+ gsk_transform_print (self, string);
+
+ return g_string_free (string, FALSE);
+}
+
+/**
+ * gsk_transform_get_transform_type:
+ * @self: (allow-none): a #GskTransform
+ *
+ * Returns the type of the @self.
+ *
+ * Returns: the type of the #GskTransform
+ */
+GskTransformType
+gsk_transform_get_transform_type (GskTransform *self)
+{
+ if (self == NULL)
+ return GSK_TRANSFORM_TYPE_IDENTITY;
+
+ return self->transform_class->transform_type;
+}
+
+/**
+ * gsk_transform_get_next:
+ * @self: (allow-none): a #GskTransform
+ *
+ * Gets the rest of the matrix in the chain of operations.
+ *
+ * Returns: (transfer none) (nullable): The next transform or
+ * %NULL if this was the last operation.
+ **/
+GskTransform *
+gsk_transform_get_next (GskTransform *self)
+{
+ if (self == NULL)
+ return NULL;
+
+ return self->next;
+}
+
+/**
+ * gsk_transform_to_matrix:
+ * @self: (allow-none): a #GskTransform
+ * @out_matrix: (out caller-allocates): The matrix to set
+ *
+ * Computes the actual value of @self and stores it in @out_matrix.
+ * The previous value of @out_matrix will be ignored.
+ **/
+void
+gsk_transform_to_matrix (GskTransform *self,
+ graphene_matrix_t *out_matrix)
+{
+ graphene_matrix_t m;
+
+ if (self == NULL)
+ {
+ graphene_matrix_init_identity (out_matrix);
+ return;
+ }
+
+ gsk_transform_to_matrix (self->next, out_matrix);
+ self->transform_class->to_matrix (self, &m);
+ graphene_matrix_multiply (&m, out_matrix, out_matrix);
+}
+
+gboolean
+gsk_transform_to_affine (GskTransform *self,
+ float *out_scale_x,
+ float *out_scale_y,
+ float *out_dx,
+ float *out_dy)
+{
+ if (self == NULL)
+ {
+ *out_scale_x = 1.0f;
+ *out_scale_y = 1.0f;
+ *out_dx = 0.0f;
+ *out_dy = 0.0f;
+ return TRUE;
+ }
+
+ if (!gsk_transform_to_affine (self->next,
+ out_scale_x, out_scale_y,
+ out_dx, out_dy))
+ return FALSE;
+
+ return self->transform_class->apply_affine (self,
+ out_scale_x, out_scale_y,
+ out_dx, out_dy);
+}
+
+/**
+ * gsk_transform_transform:
+ * @next: (allow-none) (transfer full): Transform to apply @other to
+ * @other: (allow-none): Transform to apply
+ *
+ * Applies all the operations from @other to @next.
+ *
+ * Returns: The new matrix
+ **/
+GskTransform *
+gsk_transform_transform (GskTransform *next,
+ GskTransform *other)
+{
+ if (other == NULL)
+ return next;
+
+ next = gsk_transform_transform (next, other->next);
+ return other->transform_class->apply (other, next);
+}
+
+/**
+ * gsk_transform_equal:
+ * @first: the first matrix
+ * @second: the second matrix
+ *
+ * Checks two matrices for equality. Note that matrices need to be literally
+ * identical in their operations, it is not enough that they return the
+ * same result in gsk_transform_to_matrix().
+ *
+ * Returns: %TRUE if the two matrices can be proven to be equal
+ **/
+gboolean
+gsk_transform_equal (GskTransform *first,
+ GskTransform *second)
+{
+ if (first == second)
+ return TRUE;
+
+ if (first == NULL || second == NULL)
+ return FALSE;
+
+ if (!gsk_transform_equal (first->next, second->next))
+ return FALSE;
+
+ if (first->transform_class != second->transform_class)
+ return FALSE;
+
+ return first->transform_class->equal (first, second);
+}
+
+/*<private>
+ * gsk_transform_categorize:
+ * @self: (allow-none): A matrix
+ *
+ *
+ *
+ * Returns: The category this matrix belongs to
+ **/
+GskMatrixCategory
+gsk_transform_categorize (GskTransform *self)
+{
+ if (self == NULL)
+ return GSK_MATRIX_CATEGORY_IDENTITY;
+
+ return MIN (gsk_transform_categorize (self->next),
+ self->transform_class->categorize (self));
+}
+
+/*
+ * gsk_transform_new: (constructor):
+ *
+ * Creates a new identity matrix. This function is meant to be used by language
+ * bindings. For C code, this equivalent to using %NULL.
+ *
+ * See also gsk_transform_identity() for inserting identity matrix operations
+ * when constructing matrices.
+ *
+ * Returns: A new identity matrix
+ **/
+GskTransform *
+gsk_transform_new (void)
+{
+ return gsk_transform_alloc (&GSK_IDENTITY_TRANSFORM_CLASS, NULL);
+}
--- /dev/null
+/*
+ * Copyright © 2019 Benjamin Otte
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Benjamin Otte <otte@gnome.org>
+ */
+
+
+#ifndef __GSK_TRANSFORM_H__
+#define __GSK_TRANSFORM_H__
+
+#if !defined (__GSK_H_INSIDE__) && !defined (GSK_COMPILATION)
+#error "Only <gsk/gsk.h> can be included directly."
+#endif
+
+#include <gsk/gsktypes.h>
+
+G_BEGIN_DECLS
+
+#define GSK_TYPE_TRANSFORM (gsk_transform_get_type ())
+
+typedef enum
+{
+ GSK_TRANSFORM_TYPE_IDENTITY,
+ GSK_TRANSFORM_TYPE_TRANSFORM,
+ GSK_TRANSFORM_TYPE_TRANSLATE,
+ GSK_TRANSFORM_TYPE_ROTATE,
+ GSK_TRANSFORM_TYPE_SCALE
+} GskTransformType;
+
+GDK_AVAILABLE_IN_ALL
+GType gsk_transform_get_type (void) G_GNUC_CONST;
+
+GDK_AVAILABLE_IN_ALL
+GskTransform * gsk_transform_ref (GskTransform *self);
+GDK_AVAILABLE_IN_ALL
+void gsk_transform_unref (GskTransform *self);
+
+GDK_AVAILABLE_IN_ALL
+void gsk_transform_print (GskTransform *self,
+ GString *string);
+GDK_AVAILABLE_IN_ALL
+char * gsk_transform_to_string (GskTransform *self);
+GDK_AVAILABLE_IN_ALL
+void gsk_transform_to_matrix (GskTransform *self,
+ graphene_matrix_t *out_matrix);
+GDK_AVAILABLE_IN_ALL
+gboolean gsk_transform_equal (GskTransform *first,
+ GskTransform *second) G_GNUC_PURE;
+
+GDK_AVAILABLE_IN_ALL
+GskTransform * gsk_transform_new (void);
+GDK_AVAILABLE_IN_ALL
+GskTransform * gsk_transform_identity (GskTransform *next);
+GDK_AVAILABLE_IN_ALL
+GskTransform * gsk_transform_transform (GskTransform *next,
+ GskTransform *other);
+GDK_AVAILABLE_IN_ALL
+GskTransform * gsk_transform_matrix (GskTransform *next,
+ const graphene_matrix_t *matrix);
+GDK_AVAILABLE_IN_ALL
+GskTransform * gsk_transform_translate (GskTransform *next,
+ const graphene_point_t *point);
+GDK_AVAILABLE_IN_ALL
+GskTransform * gsk_transform_translate_3d (GskTransform *next,
+ const graphene_point3d_t *point);
+GDK_AVAILABLE_IN_ALL
+GskTransform * gsk_transform_rotate (GskTransform *next,
+ float angle);
+GDK_AVAILABLE_IN_ALL
+GskTransform * gsk_transform_rotate_3d (GskTransform *next,
+ float angle,
+ const graphene_vec3_t *axis);
+GDK_AVAILABLE_IN_ALL
+GskTransform * gsk_transform_scale (GskTransform *next,
+ float factor_x,
+ float factor_y);
+GDK_AVAILABLE_IN_ALL
+GskTransform * gsk_transform_scale_3d (GskTransform *next,
+ float factor_x,
+ float factor_y,
+ float factor_z);
+
+GDK_AVAILABLE_IN_ALL
+GskTransformType gsk_transform_get_transform_type (GskTransform *self) G_GNUC_PURE;
+GDK_AVAILABLE_IN_ALL
+GskTransform * gsk_transform_get_next (GskTransform *self) G_GNUC_PURE;
+
+G_END_DECLS
+
+#endif /* __GSK_TRANSFORM_H__ */
--- /dev/null
+/*
+ * Copyright © 2019 Benjamin Otte
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Benjamin Otte <otte@gnome.org>
+ */
+
+
+#ifndef __GSK_TRANSFORM_PRIVATE_H__
+#define __GSK_TRANSFORM_PRIVATE_H__
+
+#include "gsktransform.h"
+
+#include <gsk/gsk.h>
+#include "gsk/gskrendernodeprivate.h"
+
+G_BEGIN_DECLS
+
+GskMatrixCategory gsk_transform_categorize (GskTransform *self);
+
+gboolean gsk_transform_to_affine (GskTransform *self,
+ float *scale_x,
+ float *scale_y,
+ float *dx,
+ float *dy) G_GNUC_WARN_UNUSED_RESULT;
+
+GskTransform * gsk_transform_matrix_with_category (GskTransform *next,
+ const graphene_matrix_t*matrix,
+ GskMatrixCategory category);
+
+G_END_DECLS
+
+#endif /* __GSK_TRANSFORM_PRIVATE_H__ */
+
#include <gsk/gskenums.h>
typedef struct _GskRenderer GskRenderer;
+typedef struct _GskTransform GskTransform;
#endif /* __GSK_TYPES_H__ */
'gskrenderer.c',
'gskrendernode.c',
'gskrendernodeimpl.c',
- 'gskroundedrect.c'
+ 'gskroundedrect.c',
+ 'gsktransform.c',
])
gsk_private_sources = files([
'gskrenderer.h',
'gskrendernode.h',
'gskroundedrect.h',
+ 'gsktransform.h',
'gsktypes.h',
'gsk-autocleanup.h'
])
#include <gtk/gtktoolshell.h>
#include <gtk/gtktooltip.h>
#include <gtk/gtktestutils.h>
-#include <gtk/gtktransform.h>
#include <gtk/gtktreednd.h>
#include <gtk/gtktreelistmodel.h>
#include <gtk/gtktreemodel.h>
#include <string.h>
#include "gtkcssnumbervalueprivate.h"
-#include "gtktransform.h"
+#include "gsktransform.h"
typedef union _GtkCssTransform GtkCssTransform;
transform->type = type;
}
-static GtkTransform *
+static GskTransform *
gtk_css_transform_apply (const GtkCssTransform *transform,
- GtkTransform *next)
+ GskTransform *next)
{
graphene_matrix_t skew;
switch (transform->type)
{
case GTK_CSS_TRANSFORM_MATRIX:
- return gtk_transform_matrix (next, &transform->matrix.matrix);
+ return gsk_transform_matrix (next, &transform->matrix.matrix);
case GTK_CSS_TRANSFORM_TRANSLATE:
- return gtk_transform_translate_3d (next,
+ return gsk_transform_translate_3d (next,
&GRAPHENE_POINT3D_INIT (
_gtk_css_number_value_get (transform->translate.x, 100),
_gtk_css_number_value_get (transform->translate.y, 100),
_gtk_css_number_value_get (transform->rotate.x, 1),
_gtk_css_number_value_get (transform->rotate.y, 1),
_gtk_css_number_value_get (transform->rotate.z, 1));
- return gtk_transform_rotate_3d (next,
+ return gsk_transform_rotate_3d (next,
_gtk_css_number_value_get (transform->rotate.angle, 100),
&axis);
}
case GTK_CSS_TRANSFORM_SCALE:
- return gtk_transform_scale_3d (next,
+ return gsk_transform_scale_3d (next,
_gtk_css_number_value_get (transform->scale.x, 1),
_gtk_css_number_value_get (transform->scale.y, 1),
_gtk_css_number_value_get (transform->scale.z, 1));
graphene_matrix_init_skew (&skew,
_gtk_css_number_value_get (transform->skew.x, 100) / 180.0f * G_PI,
_gtk_css_number_value_get (transform->skew.y, 100) / 180.0f * G_PI);
- return gtk_transform_matrix (next, &skew);
+ return gsk_transform_matrix (next, &skew);
case GTK_CSS_TRANSFORM_SKEW_X:
graphene_matrix_init_skew (&skew,
_gtk_css_number_value_get (transform->skew_x.skew, 100) / 180.0f * G_PI,
0);
- return gtk_transform_matrix (next, &skew);
+ return gsk_transform_matrix (next, &skew);
case GTK_CSS_TRANSFORM_SKEW_Y:
graphene_matrix_init_skew (&skew,
0,
_gtk_css_number_value_get (transform->skew_y.skew, 100) / 180.0f * G_PI);
- return gtk_transform_matrix (next, &skew);
+ return gsk_transform_matrix (next, &skew);
case GTK_CSS_TRANSFORM_NONE:
default:
}
/* NB: The returned matrix may be invalid */
-static GtkTransform *
+static GskTransform *
gtk_css_transform_value_compute_transform (const GtkCssValue *value)
{
- GtkTransform *transform;
+ GskTransform *transform;
guint i;
transform = NULL;
{
if (start->transforms[i].type != end->transforms[i].type)
{
- GtkTransform *transform;
+ GskTransform *transform;
graphene_matrix_t start_matrix, end_matrix;
transform = gtk_css_transform_value_compute_transform (start);
- gtk_transform_to_matrix (transform, &start_matrix);
- gtk_transform_unref (transform);
+ gsk_transform_to_matrix (transform, &start_matrix);
+ gsk_transform_unref (transform);
transform = gtk_css_transform_value_compute_transform (end);
- gtk_transform_to_matrix (transform, &end_matrix);
- gtk_transform_unref (transform);
+ gsk_transform_to_matrix (transform, &end_matrix);
+ gsk_transform_unref (transform);
result = gtk_css_transform_value_alloc (1);
result->transforms[0].type = GTK_CSS_TRANSFORM_MATRIX;
return value;
}
-GtkTransform *
+GskTransform *
gtk_css_transform_value_get_transform (const GtkCssValue *transform)
{
g_return_val_if_fail (transform->class == >K_CSS_VALUE_TRANSFORM, FALSE);
GtkCssValue * _gtk_css_transform_value_new_none (void);
GtkCssValue * _gtk_css_transform_value_parse (GtkCssParser *parser);
-GtkTransform * gtk_css_transform_value_get_transform (const GtkCssValue *transform);
+GskTransform * gtk_css_transform_value_get_transform (const GtkCssValue *transform);
G_END_DECLS
#include "gtkcsstransformvalueprivate.h"
#include "gtkiconthemeprivate.h"
#include "gtksnapshot.h"
-#include "gtktransform.h"
+#include "gsktransform.h"
#include <math.h>
GtkCssImageBuiltinType builtin_type)
{
const GtkCssValue *shadows_value, *transform_value, *filter_value;
- GtkTransform *transform;
+ GskTransform *transform;
GtkCssImage *image;
gboolean has_shadow;
gtk_snapshot_pop (snapshot);
- gtk_transform_unref (transform);
+ gsk_transform_unref (transform);
}
void
gboolean recolor)
{
const GtkCssValue *shadows_value, *transform_value, *filter_value;
- GtkTransform *transform;
+ GskTransform *transform;
gboolean has_shadow;
g_return_if_fail (GTK_IS_CSS_STYLE (style));
transparent:
gtk_css_filter_value_pop_snapshot (filter_value, snapshot);
- gtk_transform_unref (transform);
+ gsk_transform_unref (transform);
}
#include "gtkrendericonprivate.h"
#include "gtkrendernodepaintableprivate.h"
#include "gtkstylecontextprivate.h"
-#include "gtktransformprivate.h"
+#include "gsktransformprivate.h"
#include "gsk/gskrendernodeprivate.h"
static GtkSnapshotState *
gtk_snapshot_push_state (GtkSnapshot *snapshot,
- GtkTransform *transform,
+ GskTransform *transform,
GtkSnapshotCollectFunc collect_func)
{
const gsize n_states = snapshot->state_stack->len;
g_array_set_size (snapshot->state_stack, n_states + 1);
state = &g_array_index (snapshot->state_stack, GtkSnapshotState, n_states);
- state->transform = gtk_transform_ref (transform);
+ state->transform = gsk_transform_ref (transform);
state->collect_func = collect_func;
state->start_node_index = snapshot->nodes->len;
state->n_nodes = 0;
static void
gtk_snapshot_state_clear (GtkSnapshotState *state)
{
- gtk_transform_unref (state->transform);
+ gsk_transform_unref (state->transform);
}
/**
previous_state = gtk_snapshot_get_previous_state (snapshot);
- gtk_transform_to_matrix (previous_state->transform, &state->data.transform.transform);
- state->data.transform.category = gtk_transform_categorize (previous_state->transform);
+ gsk_transform_to_matrix (previous_state->transform, &state->data.transform.transform);
+ state->data.transform.category = gsk_transform_categorize (previous_state->transform);
}
static gboolean
{
const GtkSnapshotState *current_state = gtk_snapshot_get_current_state (snapshot);
- if (gtk_transform_to_affine (current_state->transform, scale_x, scale_y, dx, dy))
+ if (gsk_transform_to_affine (current_state->transform, scale_x, scale_y, dx, dy))
return;
gtk_snapshot_autopush_transform (snapshot);
const GtkSnapshotState *current_state = gtk_snapshot_get_current_state (snapshot);
float scale_x, scale_y;
- if (gtk_transform_to_affine (current_state->transform, &scale_x, &scale_y, dx, dy) &&
+ if (gsk_transform_to_affine (current_state->transform, &scale_x, &scale_y, dx, dy) &&
scale_x == 1.0f && scale_y == 1.0f)
return;
**/
void
gtk_snapshot_transform (GtkSnapshot *snapshot,
- GtkTransform *transform)
+ GskTransform *transform)
{
GtkSnapshotState *state;
g_return_if_fail (GTK_IS_SNAPSHOT (snapshot));
state = gtk_snapshot_get_current_state (snapshot);
- state->transform = gtk_transform_transform (state->transform, transform);
+ state->transform = gsk_transform_transform (state->transform, transform);
}
/**
g_return_if_fail (matrix != NULL);
state = gtk_snapshot_get_current_state (snapshot);
- state->transform = gtk_transform_matrix (state->transform, matrix);
+ state->transform = gsk_transform_matrix (state->transform, matrix);
}
void
g_return_if_fail (matrix != NULL);
state = gtk_snapshot_get_current_state (snapshot);
- state->transform = gtk_transform_matrix_with_category (state->transform, matrix, category);
+ state->transform = gsk_transform_matrix_with_category (state->transform, matrix, category);
}
/**
g_return_if_fail (point != NULL);
state = gtk_snapshot_get_current_state (snapshot);
- state->transform = gtk_transform_translate (state->transform, point);
+ state->transform = gsk_transform_translate (state->transform, point);
}
/**
g_return_if_fail (point != NULL);
state = gtk_snapshot_get_current_state (snapshot);
- state->transform = gtk_transform_translate_3d (state->transform, point);
+ state->transform = gsk_transform_translate_3d (state->transform, point);
}
/**
g_return_if_fail (GTK_IS_SNAPSHOT (snapshot));
state = gtk_snapshot_get_current_state (snapshot);
- state->transform = gtk_transform_rotate (state->transform, angle);
+ state->transform = gsk_transform_rotate (state->transform, angle);
}
/**
*
* Rotates @snapshot's coordinate system by @angle degrees around @axis.
*
- * For a rotation in 2D space, use gtk_transform_rotate().
+ * For a rotation in 2D space, use gsk_transform_rotate().
*/
void
gtk_snapshot_rotate_3d (GtkSnapshot *snapshot,
g_return_if_fail (axis != NULL);
state = gtk_snapshot_get_current_state (snapshot);
- state->transform = gtk_transform_rotate_3d (state->transform, angle, axis);
+ state->transform = gsk_transform_rotate_3d (state->transform, angle, axis);
}
/**
g_return_if_fail (GTK_IS_SNAPSHOT (snapshot));
state = gtk_snapshot_get_current_state (snapshot);
- state->transform = gtk_transform_scale (state->transform, factor_x, factor_y);
+ state->transform = gsk_transform_scale (state->transform, factor_x, factor_y);
}
/**
g_return_if_fail (GTK_IS_SNAPSHOT (snapshot));
state = gtk_snapshot_get_current_state (snapshot);
- state->transform = gtk_transform_scale_3d (state->transform, factor_x, factor_y, factor_z);
+ state->transform = gsk_transform_scale_3d (state->transform, factor_x, factor_y, factor_z);
}
void
void gtk_snapshot_restore (GtkSnapshot *snapshot);
GDK_AVAILABLE_IN_ALL
void gtk_snapshot_transform (GtkSnapshot *snapshot,
- GtkTransform *transform);
+ GskTransform *transform);
GDK_AVAILABLE_IN_ALL
void gtk_snapshot_transform_matrix (GtkSnapshot *snapshot,
const graphene_matrix_t*matrix);
guint start_node_index;
guint n_nodes;
- GtkTransform * transform;
+ GskTransform * transform;
GtkSnapshotCollectFunc collect_func;
union {
+++ /dev/null
-/*
- * Copyright © 2019 Benjamin Otte
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- * Authors: Benjamin Otte <otte@gnome.org>
- */
-
-
-/**
- * SECTION:gtktransform
- * @Title: GtkTransform
- * @Short_description: A description for transform operations
- *
- * #GtkTransform is an object to describe transform matrices. Unlike
- * #graphene_matrix_t, #GtkTransform retains the steps in how a transform was
- * constructed, and allows inspecting them. It is modeled after the way
- * CSS describes transforms.
- *
- * #GtkTransform objects are immutable and cannot be changed after creation.
- * This means code can safely expose them as properties of objects without
- * having to worry about others changing them.
- */
-
-#include "config.h"
-
-#include "gtktransformprivate.h"
-
-typedef struct _GtkTransformClass GtkTransformClass;
-
-#define GTK_IS_TRANSFORM_TYPE(self,type) ((self) == NULL ? (type) == GTK_TRANSFORM_TYPE_IDENTITY : (self)->transform_class->transform_type == (type))
-
-struct _GtkTransform
-{
- const GtkTransformClass *transform_class;
-
- volatile int ref_count;
- GtkTransform *next;
-};
-
-struct _GtkTransformClass
-{
- GtkTransformType transform_type;
- gsize struct_size;
- const char *type_name;
-
- void (* finalize) (GtkTransform *transform);
- GskMatrixCategory (* categorize) (GtkTransform *transform);
- void (* to_matrix) (GtkTransform *transform,
- graphene_matrix_t *out_matrix);
- gboolean (* apply_affine) (GtkTransform *transform,
- float *out_scale_x,
- float *out_scale_y,
- float *out_dx,
- float *out_dy);
- void (* print) (GtkTransform *transform,
- GString *string);
- GtkTransform * (* apply) (GtkTransform *transform,
- GtkTransform *apply_to);
- /* both matrices have the same type */
- gboolean (* equal) (GtkTransform *first_transform,
- GtkTransform *second_transform);
-};
-
-/**
- * GtkTransform: (ref-func gtk_transform_ref) (unref-func gtk_transform_unref)
- *
- * The `GtkTransform` structure contains only private data.
- */
-
-G_DEFINE_BOXED_TYPE (GtkTransform, gtk_transform,
- gtk_transform_ref,
- gtk_transform_unref)
-
-/*<private>
- * gtk_transform_is_identity:
- * @transform: (allow-none): A transform or %NULL
- *
- * Checks if the transform is a representation of the identity
- * transform.
- *
- * This is different from a transform like `scale(2) scale(0.5)`
- * which just results in an identity transform when simplified.
- *
- * Returns: %TRUE if this transform is a representation of
- * the identity transform
- **/
-static gboolean
-gtk_transform_is_identity (GtkTransform *self)
-{
- return self == NULL ||
- (GTK_IS_TRANSFORM_TYPE (self, GTK_TRANSFORM_TYPE_IDENTITY) && gtk_transform_is_identity (self->next));
-}
-
-/*< private >
- * gtk_transform_alloc:
- * @transform_class: class structure for this self
- * @next: (transfer full) Next matrix to multiply with or %NULL if none
- *
- * Returns: (transfer full): the newly created #GtkTransform
- */
-static gpointer
-gtk_transform_alloc (const GtkTransformClass *transform_class,
- GtkTransform *next)
-{
- GtkTransform *self;
-
- g_return_val_if_fail (transform_class != NULL, NULL);
-
- self = g_malloc0 (transform_class->struct_size);
-
- self->transform_class = transform_class;
- self->ref_count = 1;
- self->next = gtk_transform_is_identity (next) ? NULL : next;
-
- return self;
-}
-
-/*** IDENTITY ***/
-
-static void
-gtk_identity_transform_finalize (GtkTransform *transform)
-{
-}
-
-static GskMatrixCategory
-gtk_identity_transform_categorize (GtkTransform *transform)
-{
- return GSK_MATRIX_CATEGORY_IDENTITY;
-}
-
-static void
-gtk_identity_transform_to_matrix (GtkTransform *transform,
- graphene_matrix_t *out_matrix)
-{
- graphene_matrix_init_identity (out_matrix);
-}
-
-static gboolean
-gtk_identity_transform_apply_affine (GtkTransform *transform,
- float *out_scale_x,
- float *out_scale_y,
- float *out_dx,
- float *out_dy)
-{
- return TRUE;
-}
-
-static void
-gtk_identity_transform_print (GtkTransform *transform,
- GString *string)
-{
- g_string_append (string, "identity");
-}
-
-static GtkTransform *
-gtk_identity_transform_apply (GtkTransform *transform,
- GtkTransform *apply_to)
-{
- return gtk_transform_identity (apply_to);
-}
-
-static gboolean
-gtk_identity_transform_equal (GtkTransform *first_transform,
- GtkTransform *second_transform)
-{
- return TRUE;
-}
-
-static const GtkTransformClass GTK_IDENTITY_TRANSFORM_CLASS =
-{
- GTK_TRANSFORM_TYPE_IDENTITY,
- sizeof (GtkTransform),
- "GtkIdentityMatrix",
- gtk_identity_transform_finalize,
- gtk_identity_transform_categorize,
- gtk_identity_transform_to_matrix,
- gtk_identity_transform_apply_affine,
- gtk_identity_transform_print,
- gtk_identity_transform_apply,
- gtk_identity_transform_equal,
-};
-
-/**
- * gtk_transform_identity:
- * @next: (allow-none): the next transform operation or %NULL
- *
- * Adds an identity multiplication into the list of matrix operations.
- *
- * This operation is generally useless, but may be useful when interpolating
- * matrices, because the identity matrix can be interpolated to and from
- * everything, so an identity matrix can be used as a keyframe between two
- * different types of matrices.
- *
- * Returns: The new matrix
- **/
-GtkTransform *
-gtk_transform_identity (GtkTransform *next)
-{
- if (gtk_transform_is_identity (next))
- return next;
-
- return gtk_transform_alloc (>K_IDENTITY_TRANSFORM_CLASS, next);
-}
-
-/*** MATRIX ***/
-
-typedef struct _GtkMatrixTransform GtkMatrixTransform;
-
-struct _GtkMatrixTransform
-{
- GtkTransform parent;
-
- graphene_matrix_t matrix;
- GskMatrixCategory category;
-};
-
-static void
-gtk_matrix_transform_finalize (GtkTransform *self)
-{
-}
-
-static GskMatrixCategory
-gtk_matrix_transform_categorize (GtkTransform *transform)
-{
- GtkMatrixTransform *self = (GtkMatrixTransform *) transform;
-
- return self->category;
-}
-
-static void
-gtk_matrix_transform_to_matrix (GtkTransform *transform,
- graphene_matrix_t *out_matrix)
-{
- GtkMatrixTransform *self = (GtkMatrixTransform *) transform;
-
- graphene_matrix_init_from_matrix (out_matrix, &self->matrix);
-}
-
-static gboolean
-gtk_matrix_transform_apply_affine (GtkTransform *transform,
- float *out_scale_x,
- float *out_scale_y,
- float *out_dx,
- float *out_dy)
-{
- GtkMatrixTransform *self = (GtkMatrixTransform *) transform;
-
- switch (self->category)
- {
- case GSK_MATRIX_CATEGORY_UNKNOWN:
- case GSK_MATRIX_CATEGORY_ANY:
- case GSK_MATRIX_CATEGORY_INVERTIBLE:
- default:
- return FALSE;
-
- case GSK_MATRIX_CATEGORY_2D_AFFINE:
- *out_dx += *out_scale_x * graphene_matrix_get_value (&self->matrix, 3, 0);
- *out_dy += *out_scale_y * graphene_matrix_get_value (&self->matrix, 3, 1);
- *out_scale_x *= graphene_matrix_get_value (&self->matrix, 0, 0);
- *out_scale_y *= graphene_matrix_get_value (&self->matrix, 1, 1);
- return TRUE;
-
- case GSK_MATRIX_CATEGORY_2D_TRANSLATE:
- *out_dx += *out_scale_x * graphene_matrix_get_value (&self->matrix, 3, 0);
- *out_dy += *out_scale_y * graphene_matrix_get_value (&self->matrix, 3, 1);
- return TRUE;
-
- case GSK_MATRIX_CATEGORY_IDENTITY:
- return TRUE;
- }
-}
-
-static void
-string_append_double (GString *string,
- double d)
-{
- char buf[G_ASCII_DTOSTR_BUF_SIZE];
-
- g_ascii_formatd (buf, G_ASCII_DTOSTR_BUF_SIZE, "%g", d);
- g_string_append (string, buf);
-}
-
-static void
-gtk_matrix_transform_print (GtkTransform *transform,
- GString *string)
-{
- GtkMatrixTransform *self = (GtkMatrixTransform *) transform;
- guint i;
- float f[16];
-
- g_string_append (string, "matrix3d(");
- graphene_matrix_to_float (&self->matrix, f);
- for (i = 0; i < 16; i++)
- {
- if (i > 0)
- g_string_append (string, ", ");
- string_append_double (string, f[i]);
- }
- g_string_append (string, ")");
-}
-
-static GtkTransform *
-gtk_matrix_transform_apply (GtkTransform *transform,
- GtkTransform *apply_to)
-{
- GtkMatrixTransform *self = (GtkMatrixTransform *) transform;
-
- return gtk_transform_matrix_with_category (apply_to,
- &self->matrix,
- self->category);
-}
-
-static gboolean
-gtk_matrix_transform_equal (GtkTransform *first_transform,
- GtkTransform *second_transform)
-{
- GtkMatrixTransform *first = (GtkMatrixTransform *) first_transform;
- GtkMatrixTransform *second = (GtkMatrixTransform *) second_transform;
-
- /* Crude, but better than just returning FALSE */
- return memcmp (&first->matrix, &second->matrix, sizeof (graphene_matrix_t)) == 0;
-}
-
-static const GtkTransformClass GTK_TRANSFORM_TRANSFORM_CLASS =
-{
- GTK_TRANSFORM_TYPE_TRANSFORM,
- sizeof (GtkMatrixTransform),
- "GtkMatrixTransform",
- gtk_matrix_transform_finalize,
- gtk_matrix_transform_categorize,
- gtk_matrix_transform_to_matrix,
- gtk_matrix_transform_apply_affine,
- gtk_matrix_transform_print,
- gtk_matrix_transform_apply,
- gtk_matrix_transform_equal,
-};
-
-GtkTransform *
-gtk_transform_matrix_with_category (GtkTransform *next,
- const graphene_matrix_t *matrix,
- GskMatrixCategory category)
-{
- GtkMatrixTransform *result = gtk_transform_alloc (>K_TRANSFORM_TRANSFORM_CLASS, next);
-
- graphene_matrix_init_from_matrix (&result->matrix, matrix);
- result->category = category;
-
- return &result->parent;
-}
-
-/**
- * gtk_transform_matrix:
- * @next: (allow-none): the next transform
- * @matrix: the matrix to multiply @next with
- *
- * Multiplies @next with the given @matrix.
- *
- * Returns: The new matrix
- **/
-GtkTransform *
-gtk_transform_matrix (GtkTransform *next,
- const graphene_matrix_t *matrix)
-{
- return gtk_transform_matrix_with_category (next, matrix, GSK_MATRIX_CATEGORY_UNKNOWN);
-}
-
-/*** TRANSLATE ***/
-
-typedef struct _GtkTranslateTransform GtkTranslateTransform;
-
-struct _GtkTranslateTransform
-{
- GtkTransform parent;
-
- graphene_point3d_t point;
-};
-
-static void
-gtk_translate_transform_finalize (GtkTransform *self)
-{
-}
-
-static GskMatrixCategory
-gtk_translate_transform_categorize (GtkTransform *transform)
-{
- GtkTranslateTransform *self = (GtkTranslateTransform *) transform;
-
- if (self->point.z != 0.0)
- return GSK_MATRIX_CATEGORY_INVERTIBLE;
-
- return GSK_MATRIX_CATEGORY_2D_TRANSLATE;
-}
-
-static void
-gtk_translate_transform_to_matrix (GtkTransform *transform,
- graphene_matrix_t *out_matrix)
-{
- GtkTranslateTransform *self = (GtkTranslateTransform *) transform;
-
- graphene_matrix_init_translate (out_matrix, &self->point);
-}
-
-static gboolean
-gtk_translate_transform_apply_affine (GtkTransform *transform,
- float *out_scale_x,
- float *out_scale_y,
- float *out_dx,
- float *out_dy)
-{
- GtkTranslateTransform *self = (GtkTranslateTransform *) transform;
-
- if (self->point.z != 0.0)
- return FALSE;
-
- *out_dx += *out_scale_x * self->point.x;
- *out_dy += *out_scale_y * self->point.y;
-
- return TRUE;
-}
-
-static GtkTransform *
-gtk_translate_transform_apply (GtkTransform *transform,
- GtkTransform *apply_to)
-{
- GtkTranslateTransform *self = (GtkTranslateTransform *) transform;
-
- return gtk_transform_translate_3d (apply_to, &self->point);
-}
-
-static gboolean
-gtk_translate_transform_equal (GtkTransform *first_transform,
- GtkTransform *second_transform)
-{
- GtkTranslateTransform *first = (GtkTranslateTransform *) first_transform;
- GtkTranslateTransform *second = (GtkTranslateTransform *) second_transform;
-
- return graphene_point3d_equal (&first->point, &second->point);
-}
-
-static void
-gtk_translate_transform_print (GtkTransform *transform,
- GString *string)
-{
- GtkTranslateTransform *self = (GtkTranslateTransform *) transform;
-
- if (self->point.z == 0)
- g_string_append (string, "translate(");
- else
- g_string_append (string, "translate3d(");
-
- string_append_double (string, self->point.x);
- g_string_append (string, ", ");
- string_append_double (string, self->point.y);
- if (self->point.z != 0)
- {
- g_string_append (string, ", ");
- string_append_double (string, self->point.y);
- }
- g_string_append (string, ")");
-}
-
-static const GtkTransformClass GTK_TRANSLATE_TRANSFORM_CLASS =
-{
- GTK_TRANSFORM_TYPE_TRANSLATE,
- sizeof (GtkTranslateTransform),
- "GtkTranslateTransform",
- gtk_translate_transform_finalize,
- gtk_translate_transform_categorize,
- gtk_translate_transform_to_matrix,
- gtk_translate_transform_apply_affine,
- gtk_translate_transform_print,
- gtk_translate_transform_apply,
- gtk_translate_transform_equal,
-};
-
-/**
- * gtk_transform_translate:
- * @next: (allow-none): the next transform
- * @point: the point to translate the matrix by
- *
- * Translates @next in 2dimensional space by @point.
- *
- * Returns: The new matrix
- **/
-GtkTransform *
-gtk_transform_translate (GtkTransform *next,
- const graphene_point_t *point)
-{
- graphene_point3d_t point3d;
-
- graphene_point3d_init (&point3d, point->x, point->y, 0);
-
- return gtk_transform_translate_3d (next, &point3d);
-}
-
-/**
- * gtk_transform_translate_3d:
- * @next: (allow-none): the next transform
- * @point: the point to translate the matrix by
- *
- * Translates @next by @point.
- *
- * Returns: The new matrix
- **/
-GtkTransform *
-gtk_transform_translate_3d (GtkTransform *next,
- const graphene_point3d_t *point)
-{
- GtkTranslateTransform *result = gtk_transform_alloc (>K_TRANSLATE_TRANSFORM_CLASS, next);
-
- graphene_point3d_init_from_point (&result->point, point);
-
- return &result->parent;
-}
-
-/*** ROTATE ***/
-
-typedef struct _GtkRotateTransform GtkRotateTransform;
-
-struct _GtkRotateTransform
-{
- GtkTransform parent;
-
- float angle;
- graphene_vec3_t axis;
-};
-
-static void
-gtk_rotate_transform_finalize (GtkTransform *self)
-{
-}
-
-static GskMatrixCategory
-gtk_rotate_transform_categorize (GtkTransform *transform)
-{
- return GSK_MATRIX_CATEGORY_INVERTIBLE;
-}
-
-static void
-gtk_rotate_transform_to_matrix (GtkTransform *transform,
- graphene_matrix_t *out_matrix)
-{
- GtkRotateTransform *self = (GtkRotateTransform *) transform;
-
- graphene_matrix_init_rotate (out_matrix, self->angle, &self->axis);
-}
-
-static gboolean
-gtk_rotate_transform_apply_affine (GtkTransform *transform,
- float *out_scale_x,
- float *out_scale_y,
- float *out_dx,
- float *out_dy)
-{
- return FALSE;
-}
-
-static GtkTransform *
-gtk_rotate_transform_apply (GtkTransform *transform,
- GtkTransform *apply_to)
-{
- GtkRotateTransform *self = (GtkRotateTransform *) transform;
-
- return gtk_transform_rotate_3d (apply_to, self->angle, &self->axis);
-}
-
-static gboolean
-gtk_rotate_transform_equal (GtkTransform *first_transform,
- GtkTransform *second_transform)
-{
- GtkRotateTransform *first = (GtkRotateTransform *) first_transform;
- GtkRotateTransform *second = (GtkRotateTransform *) second_transform;
-
- return first->angle == second->angle
- && graphene_vec3_equal (&first->axis, &second->axis);
-}
-
-static void
-gtk_rotate_transform_print (GtkTransform *transform,
- GString *string)
-{
- GtkRotateTransform *self = (GtkRotateTransform *) transform;
- graphene_vec3_t default_axis;
-
- graphene_vec3_init_from_vec3 (&default_axis, graphene_vec3_z_axis ());
- if (graphene_vec3_equal (&default_axis, &self->axis))
- {
- g_string_append (string, "rotate(");
- string_append_double (string, self->angle);
- g_string_append (string, ")");
- }
- else
- {
- float f[3];
- guint i;
-
- g_string_append (string, "rotate3d(");
- graphene_vec3_to_float (&self->axis, f);
- for (i = 0; i < 3; i++)
- {
- string_append_double (string, f[i]);
- g_string_append (string, ", ");
- }
- string_append_double (string, self->angle);
- g_string_append (string, ")");
- }
-}
-
-static const GtkTransformClass GTK_ROTATE_TRANSFORM_CLASS =
-{
- GTK_TRANSFORM_TYPE_ROTATE,
- sizeof (GtkRotateTransform),
- "GtkRotateTransform",
- gtk_rotate_transform_finalize,
- gtk_rotate_transform_categorize,
- gtk_rotate_transform_to_matrix,
- gtk_rotate_transform_apply_affine,
- gtk_rotate_transform_print,
- gtk_rotate_transform_apply,
- gtk_rotate_transform_equal,
-};
-
-/**
- * gtk_transform_rotate:
- * @next: (allow-none): the next transform
- * @angle: the rotation angle, in degrees (clockwise)
- *
- * Rotates @next @angle degrees in 2D - or in 3Dspeak, around the z axis.
- *
- * Returns: The new matrix
- **/
-GtkTransform *
-gtk_transform_rotate (GtkTransform *next,
- float angle)
-{
- return gtk_transform_rotate_3d (next, angle, graphene_vec3_z_axis ());
-}
-
-/**
- * gtk_transform_rotate_3d:
- * @next: (allow-none): the next transform
- * @angle: the rotation angle, in degrees (clockwise)
- * @axis: The rotation axis
- *
- * Rotates @next @angle degrees around @axis.
- *
- * For a rotation in 2D space, use gtk_transform_rotate().
- *
- * Returns: The new matrix
- **/
-GtkTransform *
-gtk_transform_rotate_3d (GtkTransform *next,
- float angle,
- const graphene_vec3_t *axis)
-{
- GtkRotateTransform *result = gtk_transform_alloc (>K_ROTATE_TRANSFORM_CLASS, next);
-
- result->angle = angle;
- graphene_vec3_init_from_vec3 (&result->axis, axis);
-
- return &result->parent;
-}
-
-/*** SCALE ***/
-
-typedef struct _GtkScaleTransform GtkScaleTransform;
-
-struct _GtkScaleTransform
-{
- GtkTransform parent;
-
- float factor_x;
- float factor_y;
- float factor_z;
-};
-
-static void
-gtk_scale_transform_finalize (GtkTransform *self)
-{
-}
-
-static GskMatrixCategory
-gtk_scale_transform_categorize (GtkTransform *transform)
-{
- GtkScaleTransform *self = (GtkScaleTransform *) transform;
-
- if (self->factor_z != 1.0)
- return GSK_MATRIX_CATEGORY_INVERTIBLE;
-
- return GSK_MATRIX_CATEGORY_2D_AFFINE;
-}
-
-static void
-gtk_scale_transform_to_matrix (GtkTransform *transform,
- graphene_matrix_t *out_matrix)
-{
- GtkScaleTransform *self = (GtkScaleTransform *) transform;
-
- graphene_matrix_init_scale (out_matrix, self->factor_x, self->factor_y, self->factor_z);
-}
-
-static gboolean
-gtk_scale_transform_apply_affine (GtkTransform *transform,
- float *out_scale_x,
- float *out_scale_y,
- float *out_dx,
- float *out_dy)
-{
- GtkScaleTransform *self = (GtkScaleTransform *) transform;
-
- if (self->factor_z != 1.0)
- return FALSE;
-
- *out_scale_x *= self->factor_x;
- *out_scale_y *= self->factor_y;
-
- return TRUE;
-}
-
-static GtkTransform *
-gtk_scale_transform_apply (GtkTransform *transform,
- GtkTransform *apply_to)
-{
- GtkScaleTransform *self = (GtkScaleTransform *) transform;
-
- return gtk_transform_scale_3d (apply_to, self->factor_x, self->factor_y, self->factor_z);
-}
-
-static gboolean
-gtk_scale_transform_equal (GtkTransform *first_transform,
- GtkTransform *second_transform)
-{
- GtkScaleTransform *first = (GtkScaleTransform *) first_transform;
- GtkScaleTransform *second = (GtkScaleTransform *) second_transform;
-
- return first->factor_x == second->factor_x
- && first->factor_y == second->factor_y
- && first->factor_z == second->factor_z;
-}
-
-static void
-gtk_scale_transform_print (GtkTransform *transform,
- GString *string)
-{
- GtkScaleTransform *self = (GtkScaleTransform *) transform;
-
- if (self->factor_z == 1.0)
- {
- g_string_append (string, "scale(");
- string_append_double (string, self->factor_x);
- if (self->factor_x != self->factor_y)
- {
- g_string_append (string, ", ");
- string_append_double (string, self->factor_y);
- }
- g_string_append (string, ")");
- }
- else
- {
- g_string_append (string, "scale3d(");
- string_append_double (string, self->factor_x);
- g_string_append (string, ", ");
- string_append_double (string, self->factor_y);
- g_string_append (string, ", ");
- string_append_double (string, self->factor_z);
- g_string_append (string, ")");
- }
-}
-
-static const GtkTransformClass GTK_SCALE_TRANSFORM_CLASS =
-{
- GTK_TRANSFORM_TYPE_SCALE,
- sizeof (GtkScaleTransform),
- "GtkScaleTransform",
- gtk_scale_transform_finalize,
- gtk_scale_transform_categorize,
- gtk_scale_transform_to_matrix,
- gtk_scale_transform_apply_affine,
- gtk_scale_transform_print,
- gtk_scale_transform_apply,
- gtk_scale_transform_equal,
-};
-
-/**
- * gtk_transform_scale:
- * @next: (allow-none): the next transform
- * @factor_x: scaling factor on the X axis
- * @factor_y: scaling factor on the Y axis
- *
- * Scales @next in 2-dimensional space by the given factors.
- * Use gtk_transform_scale_3d() to scale in all 3 dimensions.
- *
- * Returns: The new matrix
- **/
-GtkTransform *
-gtk_transform_scale (GtkTransform *next,
- float factor_x,
- float factor_y)
-{
- return gtk_transform_scale_3d (next, factor_x, factor_y, 1.0);
-}
-
-/**
- * gtk_transform_scale_3d:
- * @next: (allow-none): the next transform
- * @factor_x: scaling factor on the X axis
- * @factor_y: scaling factor on the Y axis
- * @factor_z: scaling factor on the Z axis
- *
- * Scales @next by the given factors.
- *
- * Returns: The new matrix
- **/
-GtkTransform *
-gtk_transform_scale_3d (GtkTransform *next,
- float factor_x,
- float factor_y,
- float factor_z)
-{
- GtkScaleTransform *result = gtk_transform_alloc (>K_SCALE_TRANSFORM_CLASS, next);
-
- result->factor_x = factor_x;
- result->factor_y = factor_y;
- result->factor_z = factor_z;
-
- return &result->parent;
-}
-
-/*** PUBLIC API ***/
-
-static void
-gtk_transform_finalize (GtkTransform *self)
-{
- self->transform_class->finalize (self);
-
- gtk_transform_unref (self->next);
-
- g_free (self);
-}
-
-/**
- * gtk_transform_ref:
- * @self: (allow-none): a #GtkTransform
- *
- * Acquires a reference on the given #GtkTransform.
- *
- * Returns: (transfer none): the #GtkTransform with an additional reference
- */
-GtkTransform *
-gtk_transform_ref (GtkTransform *self)
-{
- if (self == NULL)
- return NULL;
-
- g_atomic_int_inc (&self->ref_count);
-
- return self;
-}
-
-/**
- * gtk_transform_unref:
- * @self: (allow-none): a #GtkTransform
- *
- * Releases a reference on the given #GtkTransform.
- *
- * If the reference was the last, the resources associated to the @self are
- * freed.
- */
-void
-gtk_transform_unref (GtkTransform *self)
-{
- if (self == NULL)
- return;
-
- if (g_atomic_int_dec_and_test (&self->ref_count))
- gtk_transform_finalize (self);
-}
-
-/**
- * gtk_transform_print:
- * @self: (allow-none): a #GtkTransform
- * @string: The string to print into
- *
- * Converts @self into a string representation suitable for printing that
- * can later be parsed with gtk_transform_parse().
- **/
-void
-gtk_transform_print (GtkTransform *self,
- GString *string)
-{
- g_return_if_fail (string != NULL);
-
- if (self == NULL)
- {
- g_string_append (string, "none");
- return;
- }
-
- if (self->next != NULL)
- {
- gtk_transform_print (self->next, string);
- g_string_append (string, " ");
- }
-
- self->transform_class->print (self, string);
-}
-
-/**
- * gtk_transform_to_string:
- * @self: (allow-none): a #GtkTransform
- *
- * Converts a matrix into a string that is suitable for
- * printing and can later be parsed with gtk_transform_parse().
- *
- * This is a wrapper around gtk_transform_print(), see that function
- * for details.
- *
- * Returns: A new string for @self
- **/
-char *
-gtk_transform_to_string (GtkTransform *self)
-{
- GString *string;
-
- string = g_string_new ("");
-
- gtk_transform_print (self, string);
-
- return g_string_free (string, FALSE);
-}
-
-/**
- * gtk_transform_get_transform_type:
- * @self: (allow-none): a #GtkTransform
- *
- * Returns the type of the @self.
- *
- * Returns: the type of the #GtkTransform
- */
-GtkTransformType
-gtk_transform_get_transform_type (GtkTransform *self)
-{
- if (self == NULL)
- return GTK_TRANSFORM_TYPE_IDENTITY;
-
- return self->transform_class->transform_type;
-}
-
-/**
- * gtk_transform_get_next:
- * @self: (allow-none): a #GtkTransform
- *
- * Gets the rest of the matrix in the chain of operations.
- *
- * Returns: (transfer none) (nullable): The next transform or
- * %NULL if this was the last operation.
- **/
-GtkTransform *
-gtk_transform_get_next (GtkTransform *self)
-{
- if (self == NULL)
- return NULL;
-
- return self->next;
-}
-
-/**
- * gtk_transform_to_matrix:
- * @self: (allow-none): a #GtkTransform
- * @out_matrix: (out caller-allocates): The matrix to set
- *
- * Computes the actual value of @self and stores it in @out_matrix.
- * The previous value of @out_matrix will be ignored.
- **/
-void
-gtk_transform_to_matrix (GtkTransform *self,
- graphene_matrix_t *out_matrix)
-{
- graphene_matrix_t m;
-
- if (self == NULL)
- {
- graphene_matrix_init_identity (out_matrix);
- return;
- }
-
- gtk_transform_to_matrix (self->next, out_matrix);
- self->transform_class->to_matrix (self, &m);
- graphene_matrix_multiply (&m, out_matrix, out_matrix);
-}
-
-gboolean
-gtk_transform_to_affine (GtkTransform *self,
- float *out_scale_x,
- float *out_scale_y,
- float *out_dx,
- float *out_dy)
-{
- if (self == NULL)
- {
- *out_scale_x = 1.0f;
- *out_scale_y = 1.0f;
- *out_dx = 0.0f;
- *out_dy = 0.0f;
- return TRUE;
- }
-
- if (!gtk_transform_to_affine (self->next,
- out_scale_x, out_scale_y,
- out_dx, out_dy))
- return FALSE;
-
- return self->transform_class->apply_affine (self,
- out_scale_x, out_scale_y,
- out_dx, out_dy);
-}
-
-/**
- * gtk_transform_transform:
- * @next: (allow-none) (transfer full): Transform to apply @other to
- * @other: (allow-none): Transform to apply
- *
- * Applies all the operations from @other to @next.
- *
- * Returns: The new matrix
- **/
-GtkTransform *
-gtk_transform_transform (GtkTransform *next,
- GtkTransform *other)
-{
- if (other == NULL)
- return next;
-
- next = gtk_transform_transform (next, other->next);
- return other->transform_class->apply (other, next);
-}
-
-/**
- * gtk_transform_equal:
- * @first: the first matrix
- * @second: the second matrix
- *
- * Checks two matrices for equality. Note that matrices need to be literally
- * identical in their operations, it is not enough that they return the
- * same result in gtk_transform_to_matrix().
- *
- * Returns: %TRUE if the two matrices can be proven to be equal
- **/
-gboolean
-gtk_transform_equal (GtkTransform *first,
- GtkTransform *second)
-{
- if (first == second)
- return TRUE;
-
- if (first == NULL || second == NULL)
- return FALSE;
-
- if (!gtk_transform_equal (first->next, second->next))
- return FALSE;
-
- if (first->transform_class != second->transform_class)
- return FALSE;
-
- return first->transform_class->equal (first, second);
-}
-
-/*<private>
- * gtk_transform_categorize:
- * @self: (allow-none): A matrix
- *
- *
- *
- * Returns: The category this matrix belongs to
- **/
-GskMatrixCategory
-gtk_transform_categorize (GtkTransform *self)
-{
- if (self == NULL)
- return GSK_MATRIX_CATEGORY_IDENTITY;
-
- return MIN (gtk_transform_categorize (self->next),
- self->transform_class->categorize (self));
-}
-
-/*
- * gtk_transform_new: (constructor):
- *
- * Creates a new identity matrix. This function is meant to be used by language
- * bindings. For C code, this equivalent to using %NULL.
- *
- * See also gtk_transform_identity() for inserting identity matrix operations
- * when constructing matrices.
- *
- * Returns: A new identity matrix
- **/
-GtkTransform *
-gtk_transform_new (void)
-{
- return gtk_transform_alloc (>K_IDENTITY_TRANSFORM_CLASS, NULL);
-}
+++ /dev/null
-/*
- * Copyright © 2019 Benjamin Otte
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- * Authors: Benjamin Otte <otte@gnome.org>
- */
-
-
-#ifndef __GTK_TRANSFORM_H__
-#define __GTK_TRANSFORM_H__
-
-#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
-#error "Only <gtk/gtk.h> can be included directly."
-#endif
-
-#include <graphene.h>
-#include <gtk/gtktypes.h>
-
-G_BEGIN_DECLS
-
-#define GTK_TYPE_MATRIX (gtk_transform_get_type ())
-
-typedef enum
-{
- GTK_TRANSFORM_TYPE_IDENTITY,
- GTK_TRANSFORM_TYPE_TRANSFORM,
- GTK_TRANSFORM_TYPE_TRANSLATE,
- GTK_TRANSFORM_TYPE_ROTATE,
- GTK_TRANSFORM_TYPE_SCALE
-} GtkTransformType;
-
-GDK_AVAILABLE_IN_ALL
-GType gtk_transform_get_type (void) G_GNUC_CONST;
-
-GDK_AVAILABLE_IN_ALL
-GtkTransform * gtk_transform_ref (GtkTransform *self);
-GDK_AVAILABLE_IN_ALL
-void gtk_transform_unref (GtkTransform *self);
-
-GDK_AVAILABLE_IN_ALL
-void gtk_transform_print (GtkTransform *self,
- GString *string);
-GDK_AVAILABLE_IN_ALL
-char * gtk_transform_to_string (GtkTransform *self);
-GDK_AVAILABLE_IN_ALL
-void gtk_transform_to_matrix (GtkTransform *self,
- graphene_matrix_t *out_matrix);
-GDK_AVAILABLE_IN_ALL
-gboolean gtk_transform_equal (GtkTransform *first,
- GtkTransform *second) G_GNUC_PURE;
-
-GDK_AVAILABLE_IN_ALL
-GtkTransform * gtk_transform_new (void);
-GDK_AVAILABLE_IN_ALL
-GtkTransform * gtk_transform_identity (GtkTransform *next);
-GDK_AVAILABLE_IN_ALL
-GtkTransform * gtk_transform_transform (GtkTransform *next,
- GtkTransform *other);
-GDK_AVAILABLE_IN_ALL
-GtkTransform * gtk_transform_matrix (GtkTransform *next,
- const graphene_matrix_t *matrix);
-GDK_AVAILABLE_IN_ALL
-GtkTransform * gtk_transform_translate (GtkTransform *next,
- const graphene_point_t *point);
-GDK_AVAILABLE_IN_ALL
-GtkTransform * gtk_transform_translate_3d (GtkTransform *next,
- const graphene_point3d_t *point);
-GDK_AVAILABLE_IN_ALL
-GtkTransform * gtk_transform_rotate (GtkTransform *next,
- float angle);
-GDK_AVAILABLE_IN_ALL
-GtkTransform * gtk_transform_rotate_3d (GtkTransform *next,
- float angle,
- const graphene_vec3_t *axis);
-GDK_AVAILABLE_IN_ALL
-GtkTransform * gtk_transform_scale (GtkTransform *next,
- float factor_x,
- float factor_y);
-GDK_AVAILABLE_IN_ALL
-GtkTransform * gtk_transform_scale_3d (GtkTransform *next,
- float factor_x,
- float factor_y,
- float factor_z);
-
-GDK_AVAILABLE_IN_ALL
-GtkTransformType gtk_transform_get_transform_type (GtkTransform *self) G_GNUC_PURE;
-GDK_AVAILABLE_IN_ALL
-GtkTransform * gtk_transform_get_next (GtkTransform *self) G_GNUC_PURE;
-
-G_END_DECLS
-
-#endif /* __GTK_TRANSFORM_H__ */
+++ /dev/null
-/*
- * Copyright © 2019 Benjamin Otte
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- * Authors: Benjamin Otte <otte@gnome.org>
- */
-
-
-#ifndef __GTK_TRANSFORM_PRIVATE_H__
-#define __GTK_TRANSFORM_PRIVATE_H__
-
-#include "gtktransform.h"
-
-#include <gsk/gsk.h>
-#include "gsk/gskrendernodeprivate.h"
-
-G_BEGIN_DECLS
-
-GskMatrixCategory gtk_transform_categorize (GtkTransform *self);
-
-gboolean gtk_transform_to_affine (GtkTransform *self,
- float *scale_x,
- float *scale_y,
- float *dx,
- float *dy) G_GNUC_WARN_UNUSED_RESULT;
-
-GtkTransform * gtk_transform_matrix_with_category (GtkTransform *next,
- const graphene_matrix_t*matrix,
- GskMatrixCategory category);
-
-G_END_DECLS
-
-#endif /* __GTK_TRANSFORM_PRIVATE_H__ */
-
typedef GdkSnapshot GtkSnapshot;
typedef struct _GtkStyleContext GtkStyleContext;
typedef struct _GtkTooltip GtkTooltip;
-typedef struct _GtkTransform GtkTransform;
typedef struct _GtkWidget GtkWidget;
typedef struct _GtkWidgetPath GtkWidgetPath;
typedef struct _GtkWindow GtkWindow;
#include "gtksnapshotprivate.h"
#include "gtkstylecontextprivate.h"
#include "gtktooltipprivate.h"
-#include "gtktransformprivate.h"
+#include "gsktransformprivate.h"
#include "gtktypebuiltins.h"
#include "gtkversion.h"
#include "gtkwidgetpaintableprivate.h"
const GtkAllocation *allocation,
int baseline)
{
- GtkTransform *transform;
+ GskTransform *transform;
if (allocation->x || allocation->y)
- transform = gtk_transform_translate (NULL, &GRAPHENE_POINT_INIT (allocation->x, allocation->y));
+ transform = gsk_transform_translate (NULL, &GRAPHENE_POINT_INIT (allocation->x, allocation->y));
else
transform = NULL;
baseline,
transform);
- gtk_transform_unref (transform);
+ gsk_transform_unref (transform);
}
/**
int width,
int height,
int baseline,
- GtkTransform *transform)
+ GskTransform *transform)
{
GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
GdkRectangle adjusted;
GtkCssStyle *style;
GtkBorder margin, border, padding;
graphene_matrix_t transform_matrix;
- GtkTransform *css_transform;
+ GskTransform *css_transform;
#ifdef G_ENABLE_DEBUG
GdkDisplay *display;
#endif
baseline_changed = priv->allocated_size_baseline != baseline;
size_changed = (priv->allocated_width != width ||
priv->allocated_height != height);
- transform_changed = !gtk_transform_equal (priv->allocated_transform, transform);
+ transform_changed = !gsk_transform_equal (priv->allocated_transform, transform);
/* order is important, sometimes priv->allocated_transform == transform */
- gtk_transform_ref (transform);
- gtk_transform_unref (priv->allocated_transform);
+ gsk_transform_ref (transform);
+ gsk_transform_unref (priv->allocated_transform);
priv->allocated_transform = transform;
priv->allocated_width = width;
priv->allocated_height = height;
if (css_transform)
{
- transform = gtk_transform_translate (transform, &GRAPHENE_POINT_INIT (adjusted.x, adjusted.y));
+ transform = gsk_transform_translate (transform, &GRAPHENE_POINT_INIT (adjusted.x, adjusted.y));
adjusted.x = adjusted.y = 0;
- transform = gtk_transform_translate (transform, &GRAPHENE_POINT_INIT (adjusted.width / 2, adjusted.height / 2));
- transform = gtk_transform_transform (transform, css_transform);
- transform = gtk_transform_translate (transform, &GRAPHENE_POINT_INIT (- adjusted.width / 2, - adjusted.height / 2));
+ transform = gsk_transform_translate (transform, &GRAPHENE_POINT_INIT (adjusted.width / 2, adjusted.height / 2));
+ transform = gsk_transform_transform (transform, css_transform);
+ transform = gsk_transform_translate (transform, &GRAPHENE_POINT_INIT (- adjusted.width / 2, - adjusted.height / 2));
}
get_box_margin (style, &margin);
baseline -= margin.top + border.top + padding.top;
graphene_matrix_init_translate (&priv->transform, &GRAPHENE_POINT3D_INIT (adjusted.x, adjusted.y, 0));
- gtk_transform_to_matrix (transform, &transform_matrix);
+ gsk_transform_to_matrix (transform, &transform_matrix);
graphene_matrix_multiply (&priv->transform, &transform_matrix, &priv->transform);
- priv->transform_category = gtk_transform_categorize (transform);
+ priv->transform_category = gsk_transform_categorize (transform);
if (adjusted.x || adjusted.y)
priv->transform_category = MIN (priv->transform_category, GSK_MATRIX_CATEGORY_2D_TRANSLATE);
if (!visible)
{
- g_clear_pointer (&priv->allocated_transform, gtk_transform_unref);
+ g_clear_pointer (&priv->allocated_transform, gsk_transform_unref);
priv->allocated_width = 0;
priv->allocated_height = 0;
priv->allocated_size_baseline = 0;
int width,
int height,
int baseline,
- GtkTransform *transform);
+ GskTransform *transform);
GDK_AVAILABLE_IN_ALL
GtkSizeRequestMode gtk_widget_get_request_mode (GtkWidget *widget);
GtkStyleContext *context;
/* The widget's allocated size */
- GtkTransform *allocated_transform;
+ GskTransform *allocated_transform;
int allocated_width;
int allocated_height;
gint allocated_size_baseline;
'gtktoolshell.c',
'gtktooltip.c',
'gtktooltipwindow.c',
- 'gtktransform.c',
'gtktreednd.c',
'gtktreelistmodel.c',
'gtktreemenu.c',
'gtktoolitem.h',
'gtktoolshell.h',
'gtktooltip.h',
- 'gtktransform.h',
'gtktreednd.h',
'gtktreelistmodel.h',
'gtktreemodel.h',
int baseline)
{
GtkTransformTester *self = (GtkTransformTester *)widget;
- GtkTransform *global_transform;
+ GskTransform *global_transform;
int w, h;
if (!self->test_widget)
global_transform = NULL;
- global_transform = gtk_transform_translate (global_transform, &GRAPHENE_POINT_INIT (width / 2.0f, height / 2.0f));
- global_transform = gtk_transform_rotate (global_transform, scale);
- global_transform = gtk_transform_translate (global_transform, &GRAPHENE_POINT_INIT (-w / 2.0f, -h / 2.0f));
+ global_transform = gsk_transform_translate (global_transform, &GRAPHENE_POINT_INIT (width / 2.0f, height / 2.0f));
+ global_transform = gsk_transform_rotate (global_transform, scale);
+ global_transform = gsk_transform_translate (global_transform, &GRAPHENE_POINT_INIT (-w / 2.0f, -h / 2.0f));
gtk_widget_allocate (self->test_widget,
w, h,
-1,
global_transform);
- gtk_transform_unref (global_transform);
+ gsk_transform_unref (global_transform);
}
static void